package com.zzy.demo.common.util.rsa;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;



/**
 * 
 * @author guokaige
 * @date: 2018年11月21日 下午3:31:47
 */
public  class RsaUtil {
	
    // 私钥字符串
    private static String privateKeyStr ="30820275020100300d06092a864886f70d01010105000482025f3082025b02010002818100ecdda3f9f8ed5d149bf354a637a493c07f486efe4183d25496f300f973b510f992511a4b17c64dee1f62debeb6d26099f381fe01b918b6b2dcef1e3595973a2ae457bc8d4abc86e214dc63d95ab793eab6eece76390ac4ed55feb48fcc88ff6add0997f791dec77b3496bcbe1e3e930dcc615919e2764734bef3b417d7062a1f020301000102818041309af1b05dfb91317e9ddc8551e94c407bb9f88625769ccb52a40103a460c09f516cf01fe1f70ec35a9dbd5569bf267fcb5612395420ec473c144f611556ef718f037380253cd609becea7b4bab9b3de68e2d433be5606515be5b7b88a3d9ae338c45aa1438f93832be187e118052be0c8c072e3f3f1fa54cc8b2eca4cc2e9024100f71c1063b711b191e44c9b5dae0f1058f3c0ea6bbc6e7f4c3afa70a0bc6048b2e229f81d644cb22d38e1916a39dad7035ed3374080f0e9b06528c3b266ea0e85024100f5633a780369b39d72c9e24019cbf2a66221744c3fccbe9a00e99fb9c75d0a9ca92b4785f63e517084bc69743e51733b5a1db10c41df6f73fd452093afac3153024025b39b708b4ae0cbc0884ba0146169fe185a93a9925b4d82c4f0d6e43f39757e0d7197d06c30237330dd81813288880b94992731e93a587d3841eaf1ba2ff5bd0240218a84ad6ed9fde1219592c56c41425397ca36d94d47312e5fbd8f4597889230c3b6d4b9ece4abc11383a56e6c2e39effceb5e0decdb1ba2e11597d45808d35d02404d9620e40860775099b4a8fe5179b7684cc06d9be7f0f1a62893e396debaeb7230a7b1f0e992a539d7bbebf2526f452d6b7da2ede6c8f1347bb4368cb5c5012d";
    // 公钥字符串
    private static String publicKeyStr ="30819f300d06092a864886f70d010101050003818d0030818902818100ecdda3f9f8ed5d149bf354a637a493c07f486efe4183d25496f300f973b510f992511a4b17c64dee1f62debeb6d26099f381fe01b918b6b2dcef1e3595973a2ae457bc8d4abc86e214dc63d95ab793eab6eece76390ac4ed55feb48fcc88ff6add0997f791dec77b3496bcbe1e3e930dcc615919e2764734bef3b417d7062a1f0203010001";
   
	public static final String RSA = "RSA";
	
	public static final String UTF_8 = "UTF-8";
	
	public static final String US_ASCII = "US-ASCII";
	
	public static final String SHA1_WITH_RSA = "SHA1withRSA";
	
	public static CmsKeyPair generateKeyPair(){
        CmsKeyPair CmsKeyPair = null;
		try {
			KeyPairGenerator rsa = KeyPairGenerator.getInstance(RSA);
			rsa.initialize(1024);
			KeyPair keyPair = rsa.generateKeyPair();
			PrivateKey privateKey = keyPair.getPrivate();
			PublicKey publicKey = keyPair.getPublic();

			String privateKeyStr = ByteUtils.toHexString(privateKey.getEncoded());
			String publicKeyStr =  ByteUtils.toHexString(publicKey.getEncoded());
			CmsKeyPair = new CmsKeyPair(privateKey, publicKey, privateKeyStr, publicKeyStr);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		return CmsKeyPair;
	}
	
    // 公钥加密
    public static String encryptByPublicKey(String publicKeyStr, String content) {
        String outStr = null;
		try {
			//base64编码的公钥
			byte[] decoded = ByteUtils.fromHexString(publicKeyStr);
			RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance(RSA).generatePublic(new X509EncodedKeySpec(decoded));
			//RSA加密
			Cipher cipher = Cipher.getInstance(RSA);
			cipher.init(Cipher.ENCRYPT_MODE, pubKey);
			outStr = ByteUtils.toHexString(cipher.doFinal(content.getBytes(UTF_8)) );
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
        return outStr;
    }

    // 私钥解密
    public static String decryptByPrivateKey(String privateKeyStr, String encodeStr) {
    	String content = null;
		try {
			KeyFactory keyFactory = KeyFactory.getInstance(RSA);
			byte[] privateKeyArray = privateKeyStr.getBytes();
			byte[] dataArray = encodeStr.getBytes(UTF_8);
			PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(ByteUtils.fromHexString( new String(privateKeyArray, Charset.forName(UTF_8) )));
			PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
			Cipher cipher = Cipher.getInstance(RSA);
			cipher.init(Cipher.DECRYPT_MODE, privateKey);
			content = new String(cipher.doFinal(ByteUtils.fromHexString(new String(dataArray, Charset.forName(UTF_8)))), UTF_8);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			e.printStackTrace();
		} catch (NoSuchPaddingException e) {
			e.printStackTrace();
		} catch (IllegalBlockSizeException e) {
			e.printStackTrace();
		} catch (BadPaddingException e) {
			e.printStackTrace();
		}
		return content;
    }

    // 私钥签名
    public static String sign(String content, PrivateKey privateKey) {
    	String signHex = null;
        try {
			Signature signature = Signature.getInstance(SHA1_WITH_RSA);
			signature.initSign(privateKey);
			signature.update(content.getBytes());
			byte[] sign = signature.sign();
			signHex = ByteUtils.toHexString(sign);
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (SignatureException e) {
			e.printStackTrace();
		}
        return signHex;
    }

    // 公钥验证
    public static boolean verify(String content, String sign, PublicKey publicKey) {
        try {
			Signature signature = Signature.getInstance(SHA1_WITH_RSA);
			signature.initVerify(publicKey);
			signature.update(content.getBytes());
			return signature.verify(ByteUtils.fromHexString(sign));
		} catch (InvalidKeyException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (SignatureException e) {
			e.printStackTrace();
		}
		return false;
    }

    
    public static void main(String[] args)  {
    	
    	CmsKeyPair cmsKeyPair = RsaUtil.generateKeyPair();
    	
        System.out.println("publicKeyStr:"+ cmsKeyPair.getPublicKeyStr());
        System.out.println("privateKeyStr:"+ cmsKeyPair.getPrivateKeyStr());
        
        
        String content = "woshi中国@.com";
        System.out.println("------contentText---------:" + content);
        String encodeStr = RsaUtil.encryptByPublicKey(RsaUtil.publicKeyStr, content);
        System.out.println("------encodeStr---------:" + encodeStr);
        String result = RsaUtil.decryptByPrivateKey(RsaUtil.privateKeyStr, encodeStr);
        System.out.println("------decodeStr----:" + result);
        
	}
}